//
// Created by Administrator on 2020/11/11.
//

#include "ueFsm.h"

void UE_L3_UE_SMH_Default(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    result->procRslt = O5G_RC_OK;
}

void UE_L3_UE_SMH_ProcCellSearchTrigger(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_UeL3UeInst *pUeInst;
    S_UeL1ApiMsgConfigReq configReq;

    pUeInst = evtCtxt->context;

    configReq.commMsgHdr.type = UE_L1_API_MSG_CONFIG_REQ;
    configReq.commMsgHdr.size = sizeof(configReq);
    configReq.ueIdx = pUeInst->ueIdx;
    send(gpUeL3Context->l2SockFd, &configReq, sizeof(configReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = UE_L3_UE_SM_EVENT_RECV_L1_CONFIG_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void UE_L3_UE_SMH_ProcL1ConfigRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_UeL3UeInst *pUeInst;
    S_UeL1ApiMsgSyncReq syncReq;

    pUeInst = evtCtxt->context;

    syncReq.commMsgHdr.type = UE_L1_API_MSG_SYNC_REQ;
    syncReq.commMsgHdr.size = sizeof(syncReq);
    syncReq.ueIdx = pUeInst->ueIdx;
    send(gpUeL3Context->l2SockFd, &syncReq, sizeof(syncReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = UE_L3_UE_SM_EVENT_RECV_L1_SYNC_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void UE_L3_UE_SMH_ProcL1SyncRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_UeL3UeInst *pUeInst;
    S_UeL3L2MsgConfigReq configReq;

    pUeInst = evtCtxt->context;

    configReq.commMsgHdr.type = UE_L3_L2_MSG_CONFIG_REQ;
    configReq.commMsgHdr.size = sizeof(configReq);
    configReq.ueIdx = pUeInst->ueIdx;
    send(gpUeL3Context->l2SockFd, &configReq, sizeof(configReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = UE_L3_UE_SM_EVENT_RECV_L2_CONFIG_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void UE_L3_UE_SMH_ProcL2ConfigRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_UeL3UeInst *pUeInst;
    S_UeL3L2MsgStartReq startReq;

    pUeInst = evtCtxt->context;

    startReq.commMsgHdr.type = UE_L3_L2_MSG_START_REQ;
    startReq.commMsgHdr.size = sizeof(startReq);
    startReq.ueIdx = pUeInst->ueIdx;
    send(gpUeL3Context->l2SockFd, &startReq, sizeof(startReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = UE_L3_UE_SM_EVENT_RECV_L2_START_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void UE_L3_UE_SMH_ProcL2StartRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    UE_ADD_DBG_CODE(UE_DC_L3_CELL_SEARCH_SUCC);
    result->procRslt = O5G_RC_OK;
}

FSM_DEF_BEG(UE_L3_UE_FSM, UE_L3_UE_SM_STATE_INIT)

    FSM_STATE_DEF_BEG(UE_L3_UE_SM_STATE_INIT)
        FSM_EVENT_HANDLE_DEF(UE_L3_UE_SM_EVENT_CELL_SEARCH_TRIGGER, UE_L3_UE_SMH_ProcCellSearchTrigger)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_WAIT_L1_CONFIG_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(UE_L3_UE_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_INIT)
    FSM_STATE_DEF_END(UE_L3_UE_SM_STATE_INIT)

    FSM_STATE_DEF_BEG(UE_L3_UE_SM_STATE_WAIT_L1_CONFIG_RSP)
        FSM_EVENT_HANDLE_DEF(UE_L3_UE_SM_EVENT_RECV_L1_CONFIG_RSP, UE_L3_UE_SMH_ProcL1ConfigRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_WAIT_L1_SYNC_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(UE_L3_UE_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_INIT)
    FSM_STATE_DEF_END(UE_L3_UE_SM_STATE_WAIT_L1_CONFIG_RSP)

    FSM_STATE_DEF_BEG(UE_L3_UE_SM_STATE_WAIT_L1_SYNC_RSP)
        FSM_EVENT_HANDLE_DEF(UE_L3_UE_SM_EVENT_RECV_L1_SYNC_RSP, UE_L3_UE_SMH_ProcL1SyncRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_WAIT_L2_CONFIG_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(UE_L3_UE_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_INIT)
    FSM_STATE_DEF_END(UE_L3_UE_SM_STATE_WAIT_L1_SYNC_RSP)

    FSM_STATE_DEF_BEG(UE_L3_UE_SM_STATE_WAIT_L2_CONFIG_RSP)
        FSM_EVENT_HANDLE_DEF(UE_L3_UE_SM_EVENT_RECV_L2_CONFIG_RSP, UE_L3_UE_SMH_ProcL2ConfigRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_WAIT_L2_START_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(UE_L3_UE_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_INIT)
    FSM_STATE_DEF_END(UE_L3_UE_SM_STATE_WAIT_L2_CONFIG_RSP)

    FSM_STATE_DEF_BEG(UE_L3_UE_SM_STATE_WAIT_L2_START_RSP)
        FSM_EVENT_HANDLE_DEF(UE_L3_UE_SM_EVENT_RECV_L2_START_RSP, UE_L3_UE_SMH_ProcL2StartRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_CELL_SEARCH_SUCC)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(UE_L3_UE_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, UE_L3_UE_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, UE_L3_UE_SM_STATE_INIT)
    FSM_STATE_DEF_END(UE_L3_UE_SM_STATE_WAIT_L2_START_RSP)

FSM_DEF_END(UE_L3_UE_FSM)

int32_t UE_L3_UE_SM_Init(void)
{
    uint32_t ueLoop;
    S_UeL3UeInst *pUeInst;
    char fsmInstId[64];

    gpUeL3Context->ueFsm = FSM_INIT(UE_L3_UE_FSM);
    IF_RETURN(==, NULL, gpUeL3Context->ueFsm, O5G_RC_ER, "UE_L3_UE_SM_Init() FSM_INIT(UE_L3_UE_FSM) error!\n");

    FSM_SetLogCallback(gpUeL3Context->ueFsm, O5G_FSM_Print);

    for (ueLoop = 0; ueLoop < UE_UE_INST_NUM_MAX; ueLoop++)
    {
        pUeInst = &gpUeL3Context->ueInst[ueLoop];
        snprintf(fsmInstId, sizeof(fsmInstId), "ue:%04u", pUeInst->ueIdx);
        pUeInst->ueSmInst = FSM_INST_Init(gpUeL3Context->ueFsm, fsmInstId);
        IF_RETURN(==, NULL, pUeInst->ueSmInst, O5G_RC_ER, "UE_L3_UE_SM_Init() FSM_INST_Init() error!\n");
    }

    gpUeL3Context->ueFsmEvtQue = FixRB_Create(NULL, 256, sizeof(S_FsmEventContext), FIX_RB_TYPE_NONE);
    IF_RETURN(==, NULL, gpUeL3Context->ueFsmEvtQue, O5G_RC_ER, "UE_L3_UE_SM_Init() FixRB_Create() error!\n");

    return O5G_RC_OK;
}

int32_t UE_L3_UE_SM_Final(void)
{
    uint32_t ueLoop;
    S_UeL3UeInst *pUeInst;

    for (ueLoop = 0; ueLoop < UE_UE_INST_NUM_MAX; ueLoop++)
    {
        pUeInst = &gpUeL3Context->ueInst[ueLoop];
        FSM_INST_Final(pUeInst->ueSmInst);
    }
    FSM_Final(gpUeL3Context->ueFsm);
    FixRB_Destroy(gpUeL3Context->ueFsmEvtQue);

    return O5G_RC_OK;
}

void UE_L3_UE_SM_ProcFsmEvent()
{
    int32_t rc;
    S_UeL3UeInst *pUeInst;
    uint32_t size;
    S_FsmEventContext evtCtxt;

    while (1)
    {
        size = sizeof(evtCtxt);
        rc = FixRB_Get(gpUeL3Context->ueFsmEvtQue, &evtCtxt, &size);
        IF_BREAK(!=, CSP_RC_OK, rc, NO_LOG_MESSAGE);

        pUeInst = (S_UeL3UeInst *)evtCtxt.context;
        FSM_INST_HandleEvent(pUeInst->ueSmInst, &evtCtxt);
    }
}

void UE_L3_UE_SM_IndProcess(S_OsSelectInd *pIndMsg)
{
    switch (pIndMsg->ind)
    {
    case UE_L3_INTRA_IND_MSG_UE_FSM_EVT:
        UE_L3_UE_SM_ProcFsmEvent();
        break;
    default:
        break;
    }
}

void UE_L3_UE_SM_MsgProcess(void)
{

}

void UE_L3_UE_SM_PrdProcess(void)
{

}
